home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 1 Issue 2
/
PDCD-1 - Issue 02.iso
/
_utilities
/
utilities
/
001
/
meschach
/
!Meschach
/
c
/
iter0
< prev
next >
Wrap
Text File
|
1994-08-03
|
9KB
|
389 lines
/**************************************************************************
**
** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
**
** Meschach Library
**
** This Meschach Library is provided "as is" without any express
** or implied warranty of any kind with respect to this software.
** In particular the authors shall not be liable for any direct,
** indirect, special, incidental or consequential damages arising
** in any way from use of the software.
**
** Everyone is granted permission to copy, modify and redistribute this
** Meschach Library, provided:
** 1. All copies contain this copyright notice.
** 2. All modified copies shall carry a notice stating who
** made the last modification and the date of such modification.
** 3. No charge is made for this software or works derived from it.
** This clause shall not be construed as constraining other software
** distributed on the same medium as this software, nor is a
** distribution fee considered a charge.
**
***************************************************************************/
/* iter0.c 14/09/93 */
/* ITERATIVE METHODS - service functions */
/* functions for creating and releasing ITER structures;
for memory information;
for getting some values from an ITER variable;
for changing values in an ITER variable;
see also iter.c
*/
#include <stdio.h>
#include <math.h>
#include "iter.h"
static char rcsid[] = "$Id: iter0.c,v 1.2 1994/06/20 05:22:10 des Exp $";
/* standard functions */
/* standard information */
void iter_std_info(ip,nres,res,Bres)
ITER *ip;
double nres;
VEC *res, *Bres;
{
if (nres >= 0.0)
printf(" %d. residual = %g\n",ip->steps,nres);
else
printf(" %d. residual = %g (WARNING !!! should be >= 0) \n",
ip->steps,nres);
}
/* standard stopping criterion */
int iter_std_stop_crit(ip, nres, res, Bres)
ITER *ip;
double nres;
VEC *res, *Bres;
{
/* save initial value of the residual in init_res */
if (ip->steps == 0)
ip->init_res = fabs(nres);
/* standard stopping criterium */
if (nres <= ip->init_res*ip->eps) return TRUE;
return FALSE;
}
/* iter_get - create a new structure pointing to ITER */
ITER *iter_get(lenb, lenx)
int lenb, lenx;
{
ITER *ip;
if ((ip = NEW(ITER)) == (ITER *) NULL)
error(E_MEM,"iter_get");
else if (mem_info_is_on()) {
mem_bytes(TYPE_ITER,0,sizeof(ITER));
mem_numvar(TYPE_ITER,1);
}
/* default values */
ip->shared_x = FALSE;
ip->shared_b = FALSE;
ip->k = 0;
ip->limit = ITER_LIMIT_DEF;
ip->eps = ITER_EPS_DEF;
ip->steps = 0;
if (lenb > 0) ip->b = v_get(lenb);
else ip->b = (VEC *)NULL;
if (lenx > 0) ip->x = v_get(lenx);
else ip->x = (VEC *)NULL;
ip->Ax = ip->ATx = ip->Bx = NULL;
ip->A_par = ip->AT_par = ip->B_par = NULL;
ip->info = iter_std_info;
ip->stop_crit = iter_std_stop_crit;
ip->init_res = 0.0;
return ip;
}
/* iter_free - release memory */
int iter_free(ip)
ITER *ip;
{
if (ip == (ITER *)NULL) return -1;
if (mem_info_is_on()) {
mem_bytes(TYPE_ITER,sizeof(ITER),0);
mem_numvar(TYPE_ITER,-1);
}
if ( !ip->shared_x && ip->x != NULL ) v_free(ip->x);
if ( !ip->shared_b && ip->b != NULL ) v_free(ip->b);
free((char *)ip);
return 0;
}
ITER *iter_resize(ip,new_lenb,new_lenx)
ITER *ip;
int new_lenb, new_lenx;
{
int old;
if ( ip == (ITER *) NULL)
error(E_NULL,"iter_resize");
if (new_lenx <= 0) ip->x = VNULL;
else {
old = ip->x->dim;
ip->x = v_resize(ip->x,new_lenx);
if ( ip->shared_x && old != new_lenx)
warning(WARN_SHARED_VEC,"iter_resize");
}
if (new_lenb <= 0) ip->b = VNULL;
else {
old = ip->b->dim;
ip->b = v_resize(ip->b,new_lenb);
if ( ip->shared_b && old != new_lenb)
warning(WARN_SHARED_VEC,"iter_resize");
}
return ip;
}
/* print out ip structure - for diagnostic purposes mainly */
void iter_dump(fp,ip)
ITER *ip;
FILE *fp;
{
if (ip == NULL) {
fprintf(fp," ITER structure: NULL\n");
return;
}
fprintf(fp,"\n ITER structure:\n");
fprintf(fp," ip->shared_x = %s, ip->shared_b = %s\n",
(ip->shared_x ? "TRUE" : "FALSE"),
(ip->shared_b ? "TRUE" : "FALSE") );
fprintf(fp," ip->k = %d, ip->limit = %d, ip->steps = %d, ip->eps = %g\n",
ip->k,ip->limit,ip->steps,ip->eps);
fprintf(fp," ip->x = 0x%p, ip->b = 0x%p\n",ip->x,ip->b);
fprintf(fp," ip->Ax = 0x%p, ip->A_par = 0x%p\n",ip->Ax,ip->A_par);
fprintf(fp," ip->ATx = 0x%p, ip->AT_par = 0x%p\n",ip->ATx,ip->AT_par);
fprintf(fp," ip->Bx = 0x%p, ip->B_par = 0x%p\n",ip->Bx,ip->B_par);
fprintf(fp," ip->info = 0x%p, ip->stop_crit = 0x%p, ip->init_res = %g\n",
ip->info,ip->stop_crit,ip->init_res);
fprintf(fp,"\n");
}
/* copy the structure ip1 to ip2 preserving vectors x and b of ip2
(vectors x and b in ip2 are the same before and after iter_copy2)
if ip2 == NULL then a new structure is created with x and b being NULL
and other members are taken from ip1
*/
ITER *iter_copy2(ip1,ip2)
ITER *ip1, *ip2;
{
VEC *x, *b;
int shx, shb;
if (ip1 == (ITER *)NULL)
error(E_NULL,"iter_copy2");
if (ip2 == (ITER *)NULL) {
if ((ip2 = NEW(ITER)) == (ITER *) NULL)
error(E_MEM,"iter_copy2");
else if (mem_info_is_on()) {
mem_bytes(TYPE_ITER,0,sizeof(ITER));
mem_numvar(TYPE_ITER,1);
}
ip2->x = ip2->b = NULL;
ip2->shared_x = ip2->shared_x = FALSE;
}
x = ip2->x;
b = ip2->b;
shb = ip2->shared_b;
shx = ip2->shared_x;
MEM_COPY(ip1,ip2,sizeof(ITER));
ip2->x = x;
ip2->b = b;
ip2->shared_x = shx;
ip2->shared_b = shb;
return ip2;
}
/* copy the structure ip1 to ip2 copying also the vectors x and b */
ITER *iter_copy(ip1,ip2)
ITER *ip1, *ip2;
{
VEC *x, *b;
if (ip1 == (ITER *)NULL)
error(E_NULL,"iter_copy");
if (ip2 == (ITER *)NULL) {
if ((ip2 = NEW(ITER)) == (ITER *) NULL)
error(E_MEM,"iter_copy2");
else if (mem_info_is_on()) {
mem_bytes(TYPE_ITER,0,sizeof(ITER));
mem_numvar(TYPE_ITER,1);
}
}
x = ip2->x;
b = ip2->b;
MEM_COPY(ip1,ip2,sizeof(ITER));
if (ip1->x)
ip2->x = v_copy(ip1->x,x);
if (ip1->b)
ip2->b = v_copy(ip1->b,b);
ip2->shared_x = ip2->shared_b = FALSE;
return ip2;
}
/*** functions to generate sparse matrices with random entries ***/
/* iter_gen_sym -- generate symmetric positive definite
n x n matrix,
nrow - number of nonzero entries in a row
*/
SPMAT *iter_gen_sym(n,nrow)
int n, nrow;
{
SPMAT *A;
VEC *u;
Real s1;
int i, j, k, k_max;
if (nrow <= 1) nrow = 2;
/* nrow should be even */
if ((nrow & 1)) nrow -= 1;
A = sp_get(n,n,nrow);
u = v_get(A->m);
v_zero(u);
for ( i = 0; i < A->m; i++ )
{
k_max = ((rand() >> 8) % (nrow/2));
for ( k = 0; k <= k_max; k++ )
{
j = (rand() >> 8) % A->n;
s1 = mrand();
sp_set_val(A,i,j,s1);
sp_set_val(A,j,i,s1);
u->ve[i] += fabs(s1);
u->ve[j] += fabs(s1);
}
}
/* ensure that A is positive definite */
for ( i = 0; i < A->m; i++ )
sp_set_val(A,i,i,u->ve[i] + 1.0);
V_FREE(u);
return A;
}
/* iter_gen_nonsym -- generate non-symmetric m x n sparse matrix, m >= n
nrow - number of entries in a row;
diag - number which is put in diagonal entries and then permuted
(if diag is zero then 1.0 is there)
*/
SPMAT *iter_gen_nonsym(m,n,nrow,diag)
int m, n, nrow;
double diag;
{
SPMAT *A;
PERM *px;
int i, j, k, k_max;
Real s1;
if (nrow <= 1) nrow = 2;
if (diag == 0.0) diag = 1.0;
A = sp_get(m,n,nrow);
px = px_get(n);
for ( i = 0; i < A->m; i++ )
{
k_max = (rand() >> 8) % (nrow-1);
for ( k = 0; k <= k_max; k++ )
{
j = (rand() >> 8) % A->n;
s1 = mrand();
sp_set_val(A,i,j,-s1);
}
}
/* to make it likely that A is nonsingular, use pivot... */
for ( i = 0; i < 2*A->n; i++ )
{
j = (rand() >> 8) % A->n;
k = (rand() >> 8) % A->n;
px_transp(px,j,k);
}
for ( i = 0; i < A->n; i++ )
sp_set_val(A,i,px->pe[i],diag);
PX_FREE(px);
return A;
}
/* iter_gen_nonsym -- generate non-symmetric positive definite
n x n sparse matrix;
nrow - number of entries in a row
*/
SPMAT *iter_gen_nonsym_posdef(n,nrow)
int n, nrow;
{
SPMAT *A;
PERM *px;
VEC *u;
int i, j, k, k_max;
Real s1;
if (nrow <= 1) nrow = 2;
A = sp_get(n,n,nrow);
px = px_get(n);
u = v_get(A->m);
v_zero(u);
for ( i = 0; i < A->m; i++ )
{
k_max = (rand() >> 8) % (nrow-1);
for ( k = 0; k <= k_max; k++ )
{
j = (rand() >> 8) % A->n;
s1 = mrand();
sp_set_val(A,i,j,-s1);
u->ve[i] += fabs(s1);
}
}
/* ensure that A is positive definite */
for ( i = 0; i < A->m; i++ )
sp_set_val(A,i,i,u->ve[i] + 1.0);
PX_FREE(px);
V_FREE(u);
return A;
}